package com.hmall.item.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hmall.common.domain.PageDTO;
import com.hmall.item.domain.dto.ItemDTO;
import com.hmall.item.domain.po.Item;
import com.hmall.item.domain.po.ItemDoc;
import com.hmall.item.domain.query.ItemPageQuery;
import com.hmall.item.service.IItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;

@Api(tags = "搜索相关接口")
@RestController
@RequestMapping("/search")
@RequiredArgsConstructor
public class SearchController {

    private final IItemService itemService;

    private final RestHighLevelClient esClient = new RestHighLevelClient(RestClient.builder(
            HttpHost.create("http://127.0.0.1:9200")
    ));

    @ApiOperation("搜索商品")
    @GetMapping("/list")
    public PageDTO<ItemDTO> search(ItemPageQuery query) {
        System.out.println(query);
        try {
        /*
         *   - key：搜索关键字
              - pageNo：页码
              - pageSize：每页大小
              - sortBy：排序字段
              - isAsc：是否升序
              - category：分类
              - brand：品牌
              - minPrice：价格最小值
              - maxPrice：价格最大值
         */
            // 1.建立连接
            SearchRequest request = new SearchRequest("items");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            // 2.构建布尔查询
            BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
            if (StrUtil.isNotBlank(query.getKey())) {
                boolQuery.must(QueryBuilders.matchQuery("name", query.getKey()));
            }
            if (StrUtil.isNotBlank(query.getCategory())) {
                boolQuery.filter(QueryBuilders.termQuery("category.keyword", query.getCategory()));
            }
            if (StrUtil.isNotBlank(query.getBrand())) {
                boolQuery.filter(QueryBuilders.termQuery("brand.keyword", query.getBrand()));
            }
            if (query.getMinPrice() != null || query.getMaxPrice() != null) {
                RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
                if (query.getMinPrice() != null) rangeQuery.gte(query.getMinPrice());
                if (query.getMaxPrice() != null) rangeQuery.lte(query.getMaxPrice());
                boolQuery.filter(rangeQuery);
            }

            // 高亮配置
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("name").preTags("<em>").postTags("</em>");
            sourceBuilder.highlighter(highlightBuilder);

            sourceBuilder.from((query.getPageNo() - 1) * query.getPageSize());
            sourceBuilder.size(query.getPageSize());

            String sortBy = StrUtil.isNotBlank(query.getSortBy()) ? query.getSortBy() : "updateTime";
            SortOrder sortOrder = query.getIsAsc() != null && query.getIsAsc() ? SortOrder.ASC : SortOrder.DESC;
            sourceBuilder.sort(sortBy, sortOrder);

            sourceBuilder.query(boolQuery);
            request.source(sourceBuilder);

            SearchResponse search = null;
            search = esClient.search(request, RequestOptions.DEFAULT);
            ArrayList<ItemDoc> itemDocs = new ArrayList<>();
            for (SearchHit hit : search.getHits().getHits()) {
                System.out.println("hit = " + hit);
                ItemDoc itemDoc = new ItemDoc();
                itemDoc = BeanUtil.copyProperties(hit.getSourceAsString(), ItemDoc.class);
                itemDoc.setName(hit.getHighlightFields().get("name").getFragments()[0].toString());
                itemDocs.add(itemDoc);
            }
            // TODO 返回查询结果
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 分页查询
        Page<Item> result = itemService.lambdaQuery()
                .like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
                .eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
                .eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
                .eq(Item::getStatus, 1)
                .between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
                .page(query.toMpPage("update_time", false));
        // 封装并返回
        return PageDTO.of(result, ItemDTO.class);
    }
}
